Imports System.Diagnostics.Debug
Imports System.Drawing.Printing
Imports System.Runtime.InteropServices
Public Class PrinterStatusCheck
    Public Function CheckPrinter(ByRef PrinterStr As String, _
           ByRef JobStr As String) As String
        Dim hPrinter As IntPtr
        Dim ByteBuf As Long
        Dim BytesNeeded As Int32
        Dim PI2 As New PRINTER_INFO_2
        Dim intCount As Long
        Dim JI2(intCount) As JOB_INFO_2
        Dim PrinterInfo() As Byte
        Dim JobInfo() As Byte
        Dim result As Long
        Dim LastError As Long
        Dim PrinterName As String
        Dim tempStr As String
        Dim NumJI2 As Int32
        Dim pDefaults As PRINTER_DEFAULTS

        'Set a default return value if no errors occur.
        CheckPrinter = "Printer info retrieved"
        ' PRINTER NAME
        Dim PD As New PrintDocument
        PrinterName = PD.PrinterSettings.PrinterName
        PrinterName = "RECEIPTPRINTER"
        '
        'Set the access security setting that you want.
        pDefaults.DesiredAccess = PRINTER_ACCESS_USE

        'Call the API to obtain a handle to the printer.
        'If an error occurs, display the error.
        result = API.OpenPrinter(PrinterName, hPrinter, pDefaults)
        If result = 0 Then

            CheckPrinter = "Cannot open printer " & PrinterName & _
               ", Error: " & Marshal.GetLastWin32Error()
            Exit Function
        End If

        'Initialize the BytesNeeded variable.
        BytesNeeded = 0

        'Clear the error object.
        Err.Clear()

        'Determine the buffer size that is required to obtain the printer information.
        result = API.GetPrinter(hPrinter, 2, 0&, 0, BytesNeeded)
        'Display the error message that you receive when you call the GetPrinter function,
        'and then close the printer handle.
        If Marshal.GetLastWin32Error() <> ERROR_INSUFFICIENT_BUFFER Then
            CheckPrinter = " > GetPrinter Failed on initial call! <"
            API.ClosePrinter(hPrinter)
            Exit Function
        End If
        ReDim PrinterInfo(BytesNeeded)
        ByteBuf = BytesNeeded

        'Call the GetPrinter function to obtain the status.
        result = API.GetPrinter(hPrinter, 2, PrinterInfo(0), ByteBuf, _
          BytesNeeded)

        'Check for any errors.
        If result = 0 Then
            'Get the error.
            LastError = Marshal.GetLastWin32Error()

            'Display the error message, and then close the printer handle.
            CheckPrinter = "Could not get Printer Status!  Error = " _
               & LastError
            API.ClosePrinter(hPrinter)
            Exit Function
        End If

        'Copy the contents of the printer status byte array into a
        'PRINTER_INFO_2 structure.
        PI2 = CType(DatatoDeserial(PrinterInfo, GetType(PRINTER_INFO_2), 1), PRINTER_INFO_2)
        PrinterStr = CheckPrinterStatus(PI2.Status)

        'Add the printer name, the driver, and the port to the text box.
        'PrinterStr = PrinterStr & "Printer Name = " & _
        '  GetString(PI2.pPrinterName) & vbCrLf
        'PrinterStr = PrinterStr & "Printer Driver Name = " & _
        '  GetString(PI2.pDriverName) & vbCrLf
        'PrinterStr = PrinterStr & "Printer Port Name = " & _
        '  GetString(PI2.pPortName) & vbCrLf
        'Call the API to obtain the buffer size that is required.

        result = API.EnumJobs(hPrinter, 0, &HFFFFFFFF, 2, JobInfo, 0, BytesNeeded, NumJI2)

        'If no current jobs exist, display the message.
        If BytesNeeded = 0 Then
            JobStr = "Ready"    '"No Print Jobs!"
        Else
            'Resize the byte array to hold information about the print jobs.
            ReDim JobInfo(BytesNeeded - 1)

            'Call the API to obtain the print job information.
            result = API.EnumJobs(hPrinter, 0, &HFFFFFFFF, 2, JobInfo, _
                BytesNeeded, BytesNeeded, NumJI2)

            'Check for errors.
            If result = 0 Then
                'Display the error, and then close the printer handle.
                LastError = Marshal.GetLastWin32Error()
                CheckPrinter = " > EnumJobs Failed on second call! <  Error = " _
                   & LastError
                API.ClosePrinter(hPrinter)
                Exit Function
            End If
            ReDim JI2(NumJI2)

            'Copy the contents of print job info byte array into a
            'JOB_INFO_2 structure.
            For intCount = 0 To NumJI2 - 1 ' Loop through jobs and obtain the job information.

                Try
                    Dim test As Object
                    JI2(intCount) = CType(DatatoDeserial(JobInfo, _
                        GetType(JOB_INFO_2), intCount + 1), JOB_INFO_2)

                    JobStr = JobStr & "Job ID = " & JI2(intCount).PrinterJobId & _
                       vbCrLf & "Total Pages = " & JI2(intCount).TotalPages & vbCrLf

                    tempStr = ""
                    'Check for a ready state.
                    If JI2(intCount).pStatus = 0& Then   ' If pStatus is Null, check Status.
                        If JI2(intCount).pStatus = 0 Then
                            tempStr = tempStr & "Ready!  " & vbCrLf
                        Else  'Check for the various print job states.
                            If (JI2(intCount).pStatus And JOB_STATUS_SPOOLING) Then
                                tempStr = tempStr & "Spooling  "
                            End If

                            If (JI2(intCount).pStatus And JOB_STATUS_OFFLINE) Then
                                tempStr = tempStr & "Off line  "
                            End If

                            If (JI2(intCount).pStatus And JOB_STATUS_PAUSED) Then
                                tempStr = tempStr & "Paused  "
                            End If

                            If (JI2(intCount).pStatus And JOB_STATUS_ERROR) Then
                                tempStr = tempStr & "Error  "
                            End If

                            If (JI2(intCount).pStatus And JOB_STATUS_PAPEROUT) Then
                                tempStr = tempStr & "Paper Out  "
                            End If

                            If (JI2(intCount).pStatus And JOB_STATUS_PRINTING) Then
                                tempStr = tempStr & "Printing  "
                            End If

                            If (JI2(intCount).pStatus And JOB_STATUS_USER_INTERVENTION) Then
                                tempStr = tempStr & "User Intervention Needed  "
                            End If

                            If Len(tempStr) = 0 Then
                                tempStr = "Unknown Status of " & JI2(intCount).PrinterStatus
                            End If
                        End If
                    Else

                        tempStr = Pointer_to_String(JI2(intCount).pStatus)
                    End If

                    'Report the job status.
                    JobStr = JobStr & tempStr & vbCrLf

                Catch ex As Exception
                    'MessageBox.Show(ex.Message)
                Finally
                    'Close the printer handle.
                    API.ClosePrinter(hPrinter)
                End Try
            Next intCount
        End If
    End Function
End Class

